package cn.changeforyou.ide.idea.plugin.genTestMockMvc;

import cn.changeforyou.ide.idea.plugin.MethodEditorContext;
import cn.changeforyou.ide.idea.plugin.utils.EditorUtils;
import cn.changeforyou.ide.idea.plugin.utils.PsiFileUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiCodeBlock;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiNameValuePair;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiParameterList;
import com.intellij.psi.PsiType;
import com.intellij.psi.impl.source.PsiPlainTextFileImpl;
import com.intellij.xml.util.XmlUtil;
import java.io.File;
import org.apache.xmlbeans.impl.jam.xml.JamXmlUtils;
import org.codehaus.plexus.util.StringInputStream;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.jaxen.dom.DOMXPath;

public class MainAction extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent anActionEvent) {

        Project project = anActionEvent.getProject();
        // 获取当前文件对象
        Editor editor = anActionEvent.getData(PlatformDataKeys.EDITOR);

        // 获取选中方法
        MethodEditorContext context = EditorUtils.getPsiMethodWhichCursorIn(anActionEvent);
        PsiMethod psiMethod = context.getPsi_method();
        PsiClass psiClass = context.getPsi_class();
        PsiFile javaFile = context.getJavaFile();

        if (null == psiClass || null == psiMethod) {
            System.out.println("你的光标不在一个方法中");
            return;
        }

        //收集选中方法的相关参数
        PsiAnnotation getMappingAn = psiMethod.getAnnotation("org.springframework.web.bind.annotation.GetMapping");
        PsiAnnotation postMappingAn = psiMethod.getAnnotation("org.springframework.web.bind.annotation.PostMapping");
        PsiAnnotation requestMappingAn = psiMethod.getAnnotation("org.springframework.web.bind.annotation.RequestMapping");
        PsiAnnotation responseBodyAn = psiMethod.getAnnotation("org.springframework.web.bind.annotation.RequestBody");
        PsiAnnotation restControllerAn = psiClass.getAnnotation("org.springframework.web.bind.annotation.RestController");
        PsiAnnotation controllerAn = psiClass.getAnnotation("org.springframework.stereotype.Controller");

        //判断该方法是否是mvc的接口, 如果不是 return
        if (!checkIsMvc(getMappingAn, postMappingAn, requestMappingAn, responseBodyAn, restControllerAn, controllerAn)) {
            System.out.println("该方法不是mvc的数据接口");
            return;
        }

        //查询Test类是否存在, 如果不存在, 新建
        String qualifiedName = psiClass.getQualifiedName();
        String base_output_src = "./src/test/java";
        String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
        int subPackages = (packageName.length() - packageName.replaceAll("\\.", "").length()) + 1;
        PsiDirectory subParent = PsiFileUtil.getSubParent(javaFile, subPackages);
        if (null != subParent) {
            PsiDirectory parent = subParent.getParent();
            PsiPlainTextFileImpl iml = PsiFileUtil.findImlFromButtonToTop(project, parent);
            if(null != iml) {
                String imlText = iml.getText();
                try {
                    Document doc = DocumentHelper.parseText(imlText);
                    XPath xpath = new DOMXPath("/pre:root");
                    Node node = doc.selectSingleNode("");
                } catch (DocumentException e) {
                    e.printStackTrace();
                } catch (JaxenException e) {
                    e.printStackTrace();
                }
//                JamXmlUtils.getInstance().createService(new StringInputStream(imlText))

            }
        }

        String javaPath = project.getBasePath() + "/" + base_output_src + "/" + packageName.replaceAll("\\.", "/") + psiClass.getName() + "Test.java";

        File javaFiles = new File(javaPath);
//        if(javaFile.exists()) {
//
//        }else {
//            try {
//                javaFiles.createNewFile();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }

        //查询单元测试所需要的注解, 成员变量是否存在, 不存在就添加

        //查询目标单元测试方法是否存在, 如果存在就在末尾添加1, 在检查, 直到不重复为止

        //解析请求方法, 参数, 响应, 生成尽可能自动生成参数, 预期模拟结果, 编写

        //输出
        if (null != psiMethod) {
            // 获取备注
            // 获取大括号里的内容
            PsiCodeBlock psiCodeBlock = psiMethod.getBody();
            String codeText = psiCodeBlock.getText();
            String name = psiMethod.getName();
            System.out.print("方法名: " + name + "  ");
            //获取方法注解
            PsiAnnotation[] methodAnnotations = psiMethod.getAnnotations();
            if (null != methodAnnotations && methodAnnotations.length > 0) {
                System.out.println("方法注解:");
                for (PsiAnnotation annotation : methodAnnotations) {
                    System.out.println("@" + annotation.getQualifiedName());
                    PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
                    if (null != attributes && attributes.length > 0) {
                        for (PsiNameValuePair attribute : attributes) {
                            System.out.println("[" + attribute.getName() + ":" + attribute.getValue().getText() + "]");
                        }

                    }
                }
            }
            //获取方法参数
            PsiParameterList parameterList = psiMethod.getParameterList();
            System.out.print("参数(");
            if (!parameterList.isEmpty()) {
                PsiParameter[] parameters = parameterList.getParameters();
                for (PsiParameter parameter : parameters) {
                    PsiAnnotation[] annotations = parameter.getAnnotations();
                    String annotationStr = "";
                    if (null != annotations && annotations.length > 0) {
                        for (PsiAnnotation annotation : annotations) {
                            System.out.print("@" + annotation.getQualifiedName() + " ");
                            PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
                            if (null != attributes && attributes.length > 0) {
                                for (PsiNameValuePair attribute : attributes) {
                                    annotationStr += "[" + attribute.getName() + ":" + attribute.getValue().getText() + "]";
                                }

                            }
                        }
                    }
                    PsiType type = parameter.getType();
                    String methodType = type.getCanonicalText();
                    System.out.print(annotationStr + " " + methodType + ":" + parameter.getName());
                }
            }
            System.out.println(")");
        }
    }

    private boolean checkIsMvc(PsiAnnotation getMappingAn, PsiAnnotation postMappingAn, PsiAnnotation requestMappingAn, PsiAnnotation responseBodyAn, PsiAnnotation restControllerAn,
        PsiAnnotation controllerAn) {
        if (null == controllerAn && null == restControllerAn) {
            return false;
        }
        if (null == getMappingAn && null == postMappingAn && null == requestMappingAn) {
            return false;
        }
        if (null == responseBodyAn && null == restControllerAn) {
            return false;
        }
        return true;
    }
}
